package team.lourd.network.system.own.service.imp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import team.lourd.network.system.batch.domian.ProcessCondition;
import team.lourd.network.system.batch.domian.ProcessMeta;
import team.lourd.network.system.batch.domian.ProcessPath;
import team.lourd.network.system.batch.ext.BaseCoreHandler;
import team.lourd.network.system.batch.logic.ConditionType;
import team.lourd.network.system.own.domain.netel.NEBranch;
import team.lourd.network.system.own.domain.netel.NEDiagram;
import team.lourd.network.system.own.domain.netel.NEFlowChart;
import team.lourd.network.system.own.domain.netel.NEModel;
import team.lourd.network.system.own.domain.pretrem.PMModel;
import team.lourd.network.system.own.domain.pretrem.PMType;
import team.lourd.network.system.own.repository.jpa.netel.NEBranchRepository;
import team.lourd.network.system.own.repository.jpa.netel.NEDiagramRepository;
import team.lourd.network.system.own.repository.jpa.netel.NEModelRepository;
import team.lourd.network.system.own.repository.mongo.netel.NEFlowChartRepository;
import team.lourd.network.system.own.service.INEModelService;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class NEModelServiceImpl implements INEModelService {

    @Autowired
    private NEFlowChartRepository nEFlowChartRepository;

    @Autowired
    private NEDiagramRepository nEDiagramRepository;

    @Autowired
    private NEBranchRepository nEBranchRepository;

    @Autowired
    private NEModelRepository nEModelRepository;
    // 基础的网元处理器
    private static BaseCoreHandler baseCoreHandler;

    static {
        baseCoreHandler = BaseCoreHandler.getBaseCoreHandler();
    }

    public boolean run(PMModel pmModel) {

        return false;
    }

    public static void main(String[] args) {
        NEModelServiceImpl service = new NEModelServiceImpl();
        NEFlowChart chart = new NEFlowChart();
        NEFlowChart.Cells cell1 = new NEFlowChart.Cells();
        cell1.setType("base");
        cell1.setId("1");
        cell1.setProcessExpression("http://192.168.0.10:8080/hello");
        NEFlowChart.Cells cell2 = new NEFlowChart.Cells();
        cell2.setType("app.Link");
        cell2.setId(".");
        cell2.setCondition("a = 1");
        NEFlowChart.Cells.Source source2 = new NEFlowChart.Cells.Source();
        NEFlowChart.Cells.Target target2 = new NEFlowChart.Cells.Target();
        target2.setId("2");
        source2.setId("1");
        cell2.setSource(source2);
        cell2.setTarget(target2);
        NEFlowChart.Cells cell3 = new NEFlowChart.Cells();
        cell3.setType("base");
        cell3.setId("2");
        cell3.setProcessExpression("http://192.168.0.10:8080/hello1");
        chart.setCells(Arrays.asList(cell1, cell2, cell3));
        ProcessMeta meat = analysis(chart);
        baseCoreHandler.handle(meat);
    }

    public static ProcessMeta analysis(NEFlowChart neFlowChart) {
        Map<String, ProcessMeta> knownProcessMetaMap = new HashMap<>();
        List<String> baseProcessMetaIds = new ArrayList<>();
        List<NEFlowChart.Cells> cells = neFlowChart.getCells();
        List<NEFlowChart.Cells> linkCells = cells.stream().filter((cell) -> {
            return "app.Link".equals(cell.getType());
        }).collect(Collectors.toList());
        List<NEFlowChart.Cells> modelCells = cells.stream().filter((cell) -> {
            return !"app.Link".equals(cell.getType());
        }).collect(Collectors.toList());
        modelCells.stream().forEach((modelCell) -> {
            String cellId = modelCell.getId();
            ProcessMeta meta = new ProcessMeta();
            meta.setProcessExpression(modelCell.getProcessExpression());
            meta.setType(PMType.API);
            meta.setTarget(modelCell.getProcessExpression());
            knownProcessMetaMap.put(cellId, meta);
        });
        linkCells.stream().forEach((linkCell) -> {
            baseProcessMetaIds.add(linkCell.getTarget().getId());
            ProcessCondition condition = new ProcessCondition();
            condition.setType(ConditionType.SIMPLE);
            condition.setContent(linkCell.getCondition());
            ProcessPath path = new ProcessPath();
            path.setNext(knownProcessMetaMap.get(linkCell.getTarget().getId()));
            knownProcessMetaMap.get(linkCell.getSource().getId()).getProcessPaths().add(path);
            path.setProcessConditions(Arrays.asList(condition));
        });
        ProcessMeta meta = knownProcessMetaMap.entrySet().stream().filter((entry) -> {
            return !baseProcessMetaIds.contains(entry.getKey());
        }).map((entry) -> {
            return entry.getValue();
        }).collect(Collectors.toList()).get(0);
        return meta;
    }

    @Override
    @Transactional
    public long save(NEModel model, NEBranch branch, NEDiagram nEDiagram) {

        //model.setNeBranches(Arrays.asList(branch));
        model = nEModelRepository.save(model);

        branch.setNeModel(model);
        branch = nEBranchRepository.save(branch);

        branch.setNeDiagram(nEDiagram);
        nEDiagram.setNeBranch(branch);
        nEDiagram = nEDiagramRepository.save(nEDiagram);

        return model.getId();
    }

    @Override
    public long save(NEModel model, NEBranch branch, NEFlowChart nEFlowChart) {
        NEDiagram nEDiagram = new NEDiagram();
        nEDiagram.setNEFlowChartId(nEFlowChart.getId());
        return this.save(model, branch, nEDiagram);
    }
}
